package com.bonshotels.DomainLayer.DomainModel;

import java.io.Serializable;
import java.util.Date;

import org.hibernate.Session;

import com.bonshotels.DataLayer.Hibernate.HibernateUtil;
import com.bonshotels.DomainLayer.DomainModel.BonsHotels;

/**
	 * classe Reserva.
	 * 
	 * Permet al sistema enmagatzemar les reserves realitzades pels clients.
	 * De la reserva podem coneixer les dates en que serie ocupada gracies a 
	 * una dataInici i una DataFi. El dia en que es va fer viguent la Reserva, 
	 * el client que la va realitzar, la habitacio ocupada aixi com el preu total.
	 * Tenim un idReserva, controlat pel sistema automaticament, que utilitzarem
	 * per identificarles.
	 * 
	 * Com que utilitzem el framework de persistencia
	 * Hibernate i aquest utilitza reflexio per fer la seva feina les nostres classes han d'acomplir una
	 * serie de propietats perque la reflexio del Hibernate pugui fer completament la seva feina, les
	 * classes han de ser publiques, han de tenir un constructor public buit (si no en tenen un d'explicit
	 * el per defecte ja ho es), han d'implementar Serializable, i han de tenir substituits (override) els
	 * metodes equals() i hashCode() per que identifiquin les classes a partir de la seva clau natural.
	 * Com que Reserva te com a clau natural la seva habitacio, la data d'inici i el client els hem fet servir
	 * a l'hora d'implementar equals(), hashCode().
	 * 
	 * /*@author: Ana Rebollo Pin
	 */
public class Reserva implements Serializable {
	/** Identificador de versio de la classe, es un requisit de Serializable per distingir les diverses
	 * implementacions d'una classe. */
	private static final long serialVersionUID = -6432066718917812382L;
	/** Data on comenca el periode de reserva fet per lusuari. */
	private Date dataInici;
		
	/** Ens proporciona la data en que lusuari va fer la reserva en el sistema. */
	private Date dataReserva;
		
	/** Data en que finalitza el periode de reserva fet per lusuari. */
	private Date dataFi;
		
	/** parametre controlat de forma automatica pel sistema, que serveix per identificar la reserva, ja que mai
	 *  tindrem dos idReservas iguals. Per que el Hibernate ens el generi automaticament ha de ser un long enlloc
	 *  de un String*/
	private long idReserva;
		
	/** indica el preuTotal de la reserva feta per l'usuari en les dates indicades. */
	private Float preuTotal;
		
	/** indica la habitacio que s'ocupara durant la reserva en les dates indicades. */
	private Habitacio habitacio;
		
	/** Mostra el usuari que ha fet la reserva. */
	private Client client;
		
	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + ((client == null) ? 0 : client.hashCode());
		result = prime * result
				+ ((dataInici == null) ? 0 : dataInici.hashCode());
		result = prime * result
				+ ((habitacio == null) ? 0 : habitacio.hashCode());
		return result;
	}

		@Override
		public boolean equals(Object obj) {
			if (this == obj)
				return true;
			if (obj == null)
				return false;
			if (getClass() != obj.getClass())
				return false;
			Reserva other = (Reserva) obj;
			if (client == null) {
				if (other.client != null)
					return false;
			} else if (!client.equals(other.client))
				return false;
			if (dataInici == null) {
				if (other.dataInici != null)
					return false;
			} else if (!dataInici.equals(other.dataInici))
				return false;
			if (habitacio == null) {
				if (other.habitacio != null)
					return false;
			} else if (!habitacio.equals(other.habitacio))
				return false;
			return true;
		}
		
	/**
	 * Obte el serialversionuid.
	 *
	 * @return serialVersionUID
	 */
	public static long getSerialversionuid() {
			return serialVersionUID;
		}
	
	/**
	 * Instancia una nova Reserva.
	 */
	public Reserva() {
		
	}
		
	/**
	 * Crea una nova instacia de reserva, posant com a atributs els parametres rebuts, 
	 * a mes per asignar una valor al atribut que indica el dia en que es realitza la
	 * reserva utilitza l'operacio obteAvui de la calsse BonsHotels del sistema, la 
	 * la base de dades asigna un id a la Reserva. Afegeix la Reserva a l'habitacio.
	 *
	 * @param habitacio que volem assignar a la reserva.
	 * @param client que ha fet la reserva. 
	 * @param dataini data in comenzara la reserva.
	 * @param dataFi data on finaalitzara la reserva
	 * @param preuTotal cost final de realitzar la reserva.
	 */
	public Reserva( Habitacio habitacio, Client client, Date dataini, Date dataFi, float preuTotal) {
		Session session = HibernateUtil.getSessionFactory().getCurrentSession();
		dataInici = dataini;
		this.dataFi = dataFi;
		this.preuTotal = preuTotal;
		this.habitacio = habitacio;
		this.client = client;
		
		this.habitacio.afegeixReserva(this);
		session.save(this.habitacio);
		
		BonsHotels bonsHotels = BonsHotels.obteInstancia();
		this.dataReserva = bonsHotels.obteAvui();
		session.save(this);
		
	}
	
	/**
	 * Ens permet saber si dues reservas es solapan en el temps, i aixi evitar oferir
	 * a dos personas diferents la mateixa habitacio en dias coincidents.
	 * 
	 * @param dIni data inicial del periode en que volem saber si existeix ja una reserva 
	 * @param dFi data final del periode en que volem saber si existeix ja una reserva
	 * @return cert si en algun dels dies del periode indicat per els parametres de la funcio
	 * la habitacio ja estaba reservada fals en cas contrari.
	 */
	public boolean esSolapa(Date dIni, Date dFi) {
		int compara1 = dataInici.compareTo(dIni); 
		int compara2 = dataInici.compareTo(dFi);
		int compara3 = dataFi.compareTo(dIni);
		int compara4 = dataFi.compareTo(dFi);
		
		if (compara1 >=0 && compara2 < 0) return true;
		else if (compara3 > 0 && compara4 <= 0) return true;
		else if (compara1 <= 0 && compara4 >= 0) return true;
		else return false;
	}

	/**
	 * Obte la data inici.
	 *
	 * @return  dataInici
	 */
	public Date getDataInici() {
		return dataInici;
	}

	/**
	 * Modifica la data inici donantli el valor del parametre rebut.
	 *
	 * @param dataInici per la que sustituim el valor de la dataInici anterir de la classe
	 */
	public void setDataInici(Date dataInici) {
		this.dataInici = dataInici;
	}

	/**
	 * Obte la data reserva.
	 *
	 * @return dataReserva
	 */
	public Date getDataReserva() {
		return dataReserva;
	}

	/**
	 * Modifica la data de la reserva donantli el valor del parametre rebut.
	 *
	 * @param dataReserva per la que sustituim el valor de la dataReserva anterior de la classe
	 */
	public void setDataReserva(Date dataReserva) {
		this.dataReserva = dataReserva;
	}

	/**
	 * Obte la data fi.
	 *
	 * @return la dataFi
	 */
	public Date getDataFi() {
		return dataFi;
	}

	/**
	* Modifica la data final donantli el valor del parametre rebut.
	 *
	 * @param dataFi per la que sustituim el valor de la dataFi anterior de la classe
	 */
	public void setDataFi(Date dataFi) {
		this.dataFi = dataFi;
	}

	/**
	 * Obte id reserva.
	 *
	 * @return idReserva
	 */
	public long getIdReserva() {
		return idReserva;
	}

	/**
	 * Modifica el id reserva donantli el valor rebut com a parametre.
	 *
	 * @param idReserva valor pel que sustituirem l idReserva anterior
	 */
	public void setIdReserva(long idReserva) {
		this.idReserva = idReserva;
	}

	/**
	 * Obte preu total.
	 *
	 * @return preuTotal
	 */
	public Float getPreuTotal() {
		return preuTotal;
	}

	/**
	 * Modifica el preuTotal donantli el valor rebut com a parametre.
	 *
	 * @param preuTotal per el que volem sustituir
	 */
	public void setPreuTotal(Float preuTotal) {
		this.preuTotal = preuTotal;
	}

	/**
	 * Obte la habitacio de la Reserva.
	 *
	 * @return Habitacio
	 */
	public Habitacio getHabitacio() {
		return habitacio;
	}

	/**
	 *Modifica la habitacio donantli el valor rebut com a parametre.
	 *
	 * @param habitacio per la que sustituirem
	 */
	public void setHabitacio(Habitacio habitacio) {
		this.habitacio = habitacio;
	}

	/**
	 * Obte el client de la Reserva.
	 *
	 * @return Client
	 */
	public Client getClient() {
		return client;
	}

	/**
	 * Modifica el client asignantli el valor rebut com a parametre.
	 *
	 * @param client pel que sustituirem
	 */
	public void setClient(Client client) {
		this.client = client;
	}
}
